#include "ptwrap.hpp"
#include <nspr4/prtypes.h>
#include <nspr4/pratom.h>
#include <stdio.h>
#include <unistd.h>

class hold 
{
public:
	hold() : count_(0)
	{ }
	
	// DEBUG to

// [[ex03cb]]
// DEBUG descr Atomic operations for the general hold.
	void acquire() 
	{
		PR_AtomicIncrement(&count_);
	}

	// returns the number of holds left
	int release() 
	{
		int ret = PR_AtomicDecrement(&count_);
		if (ret == 0) {
			cond_.broadcastlock();
		}
		return ret;
	}
// END
	
	// DEBUG from

	void wait()
	{
		pw::lockmutex lm(cond_);
		while(count_ != 0) 
			cond_.wait();
	}

	int get_hold_count()
	{
		pw::lockmutex lm(cond_);
		return count_;
	}

protected:
	pw::pmcond cond_; // signaled when count_ drops to 0
	PRInt32 count_; // count of holds
};

// DEBUG {

hold hld;

class waiter : public pw::pwthread
{
public:
	// auto-start on construction and stop before destruction
	waiter()
	{
		start();
	}
	~waiter()
	{
		join();
	}
	void *execute()
	{
		hld.wait();
		fprintf(stderr, "wait succeeded\n");
		return 0;
	}
};

int main()
{
	hld.acquire();
	hld.acquire();
	fprintf(stderr, "hold count = %d\n", hld.get_hold_count());
	{ 
		waiter w;
		fprintf(stderr, "hold release = %d\n", hld.release());
		fprintf(stderr, "hold release = %d\n", hld.release());
	};

	return 0;
}
// DEBUG }
/* Sample output:

hold count = 2
hold release = 1
wait succeeded
hold release = 0

*/
